/*
 * 创建日期 2009-12-14
 *
 * 成都天和软件公司
 * 电话：028-85425861
 * 传真：028-85425861-8008
 * 邮编：610041 
 * 版权所有
 */

package  org.fantasy.common.grid.head;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Element;

import  org.fantasy.common.grid.bean.Column;
import  org.fantasy.common.util.StringUtil;
import  org.fantasy.common.util.XMLUtil;

/**
 *  功能说明
 * @author: 王文成
 * @version: 1.0
 * @since 2009-12-14
 */

public abstract class BaseTableHead {

    private static final Log log = LogFactory.getLog(BaseTableHead.class);

    /**
     * 字段名称
     */
    public static final String FIELD_NAME = "fieldName";

    /**
     * 字段描述
     */
    public static final String FIELD_LABEL = "fieldLabel";

    /**
     * 是否显示
     */
    public static final String VISIBLE = "visible";

    /**
     * 数据类型 Number | String
     */
    public static final String DATA_TYPE = "dataType";

    /**
     * 点击事件
     */
    public static final String ONCLICK = "click";

    /**
     * 宽度
     */
    public static final String WIDTH = "width";

    /**
     * 百分比
     */
    public static final String PERCENT = "percent";

    /**
     * 行高
     */
    public static final String ROW_HEIGHT = "rowHeight";

    /**
     * 属性标签
     */
    public static final String ATTRIBUTE = "attribute";

    /**
     * 参数标签
     */
    public static final String PARAM = "param";

    /**
     * 列标签
     */
    public static final String COLUMN = "column";

    /**
     * 是否是字段
     */
    public static final String ISFIELD = "isField";

    /**
     * 字段是否需要合计
     */
    public static final String IS_SUM = "isSum";

    /**
     * 纵向合并
     */
    public static final String ROWSPAN = "rowspan";

    /**
     * 横向合并
     */
    public static final String COLSPAN = "colspan";

    protected HttpServletRequest request;

    protected HttpSession session;

    protected Element tableElement;

    protected String tableConfig;

    public BaseTableHead(HttpServletRequest request, String tableConfig) throws Exception {
        this.request = request;
        this.session = request.getSession();
        this.tableConfig = tableConfig;
    }

    /**
     * 初始化表头
     * 
     * @return
     * @throws Exception
     */
    private Element prepareTableElement() throws Exception {
        if (tableElement == null) {
            tableElement = getTableElement();
        }
        return tableElement;
    }

    /**
     * 取得表头
     * 
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public List<List<Column>> getTableHeads() throws Exception {
        /* 取所有的表头配置 */
        Element tableElement = prepareTableElement();
        List<Object> rows = tableElement.selectNodes(".//row");
        // 构造一个具有所有列属性得list
        List<List<Column>> heads = new ArrayList<List<Column>>();
        // 原始配置
        if (rows.isEmpty()) {
            heads.add(getOldTableHeads());
        }
        // 如果是复杂表头配置
        else {
            List<Element> columns = (List<Element>) XMLUtil.children(tableElement, "column");
            heads = getComplexTableHeads(heads, columns, 0, "#");
        }
        return heads;

    }

    /**
     * 取得数据字段列表
     * 
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public List<Column> getTableFields() throws Exception {
        Element tableElement = prepareTableElement();
        /* 取所有的表头配置 */
        List<Object> columns = tableElement.selectNodes(".//column");
        // 构造一个具有所有列属性得list
        List<Column> fields = new ArrayList<Column>(columns.size());
        for (int i = 0; i < columns.size(); i++) {
            Element columnElement = (Element) columns.get(i);
            List rows = XMLUtil.children(columnElement, "row");
            List attributes = XMLUtil.children(columnElement, ATTRIBUTE);
            Column column = getColumn(attributes);
            column.setDesc("#" + column.getId() + "#");
            if (rows.isEmpty())
                fields.add(column);
        }
        return fields;
    }

    /**
     * 需要隐藏的表头
     * 
     * @return
     * @throws Exception
     */
    public Set<String> getHideHeads(String identity) throws Exception {
        return new HashSet<String>();
    }

    /**
     * 取得Table节点
     * 
     * @return
     * @throws Exception
     */
    protected abstract Element getTableElement() throws Exception;

    /**
     * 取得列属性
     * 
     * @param attrList
     * @return
     */
    private Column getColumn(List<Element> attrList) throws Exception {
        Column column = new Column();
        Class cls = column.getClass();
        Class[] params = new Class[] { String.class };
        for (Element element : attrList) {
            String param = element.attributeValue(PARAM);
            String value = element.getText();
            String methodName = "set" + StringUtil.firstCharUpperCase(param);
            Method method = cls.getMethod(methodName, params);
            method.invoke(column, value);
        }
        return column;
    }

    /**
     * 准备表头数据
     * 
     * @param deep
     */
    private void prepareComplexTableHeads(List<List<Column>> heads, int deep) {
        if (heads.size() < deep + 1)
            heads.add(new ArrayList<Column>());
    }

    /**
     * 创建复合表头
     * 
     * @param elements
     * @param deep
     * @throws Exception
     */
    @SuppressWarnings("all")
    private List<List<Column>> getComplexTableHeads(List<List<Column>> heads, List<Element> elements, int deep,
            String desc) throws Exception {
        prepareComplexTableHeads(heads, deep);
        for (int i = 0; i < elements.size(); i++) {
            Element column = (Element) elements.get(i);
            List attributes = XMLUtil.children(column, ATTRIBUTE);
            Column bean = getColumn(attributes);
            heads.get(deep).add(bean);
            List rows = XMLUtil.children(column, "row");
            // 列描述
            bean.setIsField(String.valueOf(rows.isEmpty()));
            Map<String, String> param = getColMap(column, bean.getId());
            bean.setColspan(param.get("colspan"));
            bean.setDesc(param.get("desc"));
            if (!rows.isEmpty()) {
                Element row = (Element) rows.get(0);
                List<Element> columns = (List<Element>) XMLUtil.children(row, "column");
                getComplexTableHeads(heads, columns, deep + 1, bean.getDesc());
            }
        }
        return heads;
    }

    /**
     * 取得colspan
     * 
     * @param column
     * @return
     * @throws Exception
     */
    @SuppressWarnings("all")
    private HashMap<String, String> getColMap(Element element, String id) throws Exception {
        int colspan = 0;
        StringBuffer desc = new StringBuffer("#" + id + "#");
        List<Object> elements = element.selectNodes(".//column");
        for (int i = 0; i < elements.size(); i++) {
            Element e = (Element) elements.get(i);
            List attributes = XMLUtil.children(e, ATTRIBUTE);
            Column column = getColumn(attributes);
            if (isField(e))
                colspan++;
            desc.append(column.getId() + "#");
        }
        HashMap<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("desc", desc.toString());
        paramMap.put("colspan", colspan > 0 ? String.valueOf(colspan) : null);
        return paramMap;
    }

    /**
     * 是否是字段，判断是否有下级。
     * 
     * @param column
     * @return
     */
    private boolean isField(Element column) {
        List rows = XMLUtil.children(column, "row");
        return rows.isEmpty();
    }

    /**
     * 兼容原始表头配置
     * 
     * @return
     * @throws Exception
     */
    private List<Column> getOldTableHeads() throws Exception {
        return getTableFields();
    }

    public List<String> getSumCols() throws Exception {
        return new ArrayList<String>(0);
    }

    public List<String> getStatCols() throws Exception {
        return new ArrayList<String>(0);
    }

    public String getSubTotal() throws Exception {
        return "false";
    }

    public String getSumTotal() throws Exception {
        return "false";
    }
}